import React, { Children, createContext, FC, useRef, useState, useEffect } from "react";
import classNames from "classnames";
import { Input } from '../input'
import Transition from '../transition/transition'
import { optionsProps } from './option'
import Icon from '../icon'
import useClickOutside from '../../hooks/useClickOutside'

export interface selectProps {
    defaultValue?: string | string[] //	指定默认选中的条目 可以是是字符串或者字符串数组
    placeholder?: string //	选择框默认文字
    disabled?: boolean //	是否禁用
    multiple?: boolean //	是否支持多选
    name?: string //viking //select	select input 的 name 属性
    onChange?: (selectedValue: string, selectedValues: string[]) => void //	选中值发生变化时触发
    onVisibleChange?: (visible: boolean) => void //	下拉框出现 / 隐藏时触发
}
// 上下文 
type optionFc = (value: string, isSelected?: boolean) => void
export interface ISelectContext {
    onSelect?: optionFc
    selectedValues: string[]
    multiple?: boolean
}
export const SelectContext = createContext<ISelectContext>({ selectedValues: [] })

const Select: FC<selectProps> = (props) => {
    // props 
    const { defaultValue, placeholder, disabled, multiple, name, onChange, onVisibleChange, children } = props
    // state 
    const [menuOpen, setMenuOpen] = useState(false)
    const [value, setValue] = useState('')
    const [selectedValues, setSelectedValues] = useState(Array.isArray(defaultValue) ? defaultValue : [])

    // other
    const containerClass = classNames('viking-select', {
        'menu-is-open': menuOpen,
        'is-disabled': disabled,
        'is-multiple': multiple,
    })
    const containerRef = useRef<HTMLDivElement>(null)
    const containerWidth = useRef(0);
    // useEffect 
    useEffect(() => {
        if (containerRef.current !== null) {
            containerWidth.current = containerRef.current.getBoundingClientRect().width;
        }
    })

    // methods
    // 上下文-处理
    const handleOption: optionFc = (value, isSelected) => {
        if (!multiple) {
            setMenuOpen(false)
            setValue(value)
            onVisibleChange && onVisibleChange(false)
        } else {
            setValue('   '); //input不能直接为'' 中间要有可个 不然placeholder会显示 
        }
        let updatedValues = [value]
        if (multiple) {
            // 处理往数组里面增加--删除item
            updatedValues = spreadArrays(selectedValues, [value])
            setSelectedValues(updatedValues)
        }
        onChange && onChange(value, updatedValues)
    }
    const selectContext: ISelectContext = {
        selectedValues: selectedValues,
        multiple: multiple,
        onSelect: handleOption
    }
    const spreadArrays = (selectedValues: string[], currVal: string[]) => {
        const idx = selectedValues.findIndex(item => item === currVal[0])
        // if (idx !== -1) {
        //     setSelectedValues(preList => preList.filter((item, index) => index !== idx))
        // } else {
        //     setSelectedValues([...selectedValues, currVal[0]])
        // }
        // 上面是异步的 那样处理就拿不到动态的值了
        if (idx !== -1) {
            // 有值的情况--删除
            return selectedValues.filter((item, index) => index !== idx)
        } else {
            // 没值-增加
            return [...selectedValues, currVal[0]]
        }
    }
    // 点击外面关闭弹窗
    const clickOutside = () => {
        setMenuOpen(false);
        if (onVisibleChange && menuOpen) {
            onVisibleChange(false);
        }
    }
    useClickOutside(containerRef, clickOutside)
    // 点击表单
    const handleInput = (e: React.MouseEvent) => {
        if (disabled) return
        e.preventDefault()
        setMenuOpen(!menuOpen)
        onVisibleChange && onVisibleChange(!menuOpen);
    }
    // 渲染options
    const generateOptions = () => {
        return Children.map(children, (child, idx) => {
            const childrenElement = child as React.FunctionComponentElement<optionsProps>
            const { displayName } = childrenElement.type
            if (displayName === 'Option') {
                return React.cloneElement(childrenElement, { index: "select-" + idx })
            } else {
                console.error('warn:Option has a child which is ');
            }
        })
    }
    // 渲染tags标签
    const tagsTemplate = () => {
        if (!multiple) return <></>
        return (
            <div className='viking-selected-tags' style={{ maxWidth: containerWidth.current - 32 }}>
                {selectedValues.map((value, index) => {
                    return (
                        <span className='viking-tag' key={"tag-" + index}>
                            {value}
                            <Icon icon='times' onClick={() => handleOption(value, true)}></Icon>
                        </span>
                    )
                })}
            </div>
        )
    }
    return (
        <div className={containerClass} ref={containerRef}>
            <div className={"viking-select-input"} onClick={handleInput}>
                <Input placeholder={placeholder} name={name} disabled={disabled} icon='angle-down'
                    readOnly={true} value={value} />
            </div>
            <SelectContext.Provider value={selectContext}>
                <Transition in={menuOpen} timeout={300} animation="zoom-in-top" >
                    <ul className='viking-select-dropdown'>
                        {generateOptions()}
                    </ul>
                </Transition>
            </SelectContext.Provider>
            {tagsTemplate()}
        </div>
    )
}

Select.defaultProps = {
    placeholder: '选择',
    name: 'viking-select'
}


export default Select